Refactored GtkSizeGroup for GtkExtendedLayout
authorTristan Van Berkom <tristan.van.berkom@gmail.com>
Sat, 17 Apr 2010 05:46:59 +0000 (01:46 -0400)
committerTristan Van Berkom <tristan.van.berkom@gmail.com>
Sat, 17 Apr 2010 05:46:59 +0000 (01:46 -0400)
Removed _gtk_size_group_compute_requisition and
_gtk_size_group_get_child_requisition in favor of
_gtk_size_group_bump_requisition() which does an orientation
contextual computation of the size group and returns the
collective value in one pass.

gtk/gtksizegroup.c
gtk/gtksizegroup.h
gtk/gtkwidget.c

index 43ae77ea5ddd23041c1cbd57c72fda0cd3337671..c6723902307b0ddfba467b0debfc2d3afc214611 100644 (file)
@@ -25,6 +25,7 @@
 #include "gtkprivate.h"
 #include "gtksizegroup.h"
 #include "gtkbuildable.h"
+#include "gtkextendedlayout.h"
 #include "gtkalias.h"
 
 enum {
@@ -71,6 +72,9 @@ static const gchar size_groups_tag[] = "gtk-size-groups";
 static GQuark visited_quark;
 static const gchar visited_tag[] = "gtk-size-group-visited";
 
+static GQuark bumping_quark;
+static const gchar bumping_tag[] = "gtk-size-group-bumping";
+
 static GSList *
 get_size_groups (GtkWidget *widget)
 {
@@ -102,6 +106,18 @@ is_visited (gpointer object)
   return g_object_get_qdata (object, visited_quark) != NULL;
 }
 
+static void
+mark_bumping (gpointer object, gboolean bumping)
+{
+  g_object_set_qdata (object, bumping_quark, bumping ? "bumping" : NULL);
+}
+
+static gboolean
+is_bumping (gpointer object)
+{
+  return g_object_get_qdata (object, bumping_quark) != NULL;
+}
+
 static void
 add_group_to_closure (GtkSizeGroup    *group,
                      GtkSizeGroupMode mode,
@@ -286,6 +302,7 @@ initialize_size_group_quarks (void)
     {
       size_groups_quark = g_quark_from_static_string (size_groups_tag);
       visited_quark = g_quark_from_static_string (visited_tag);
+      bumping_quark = g_quark_from_static_string (bumping_tag);
     }
 }
 
@@ -609,57 +626,35 @@ get_base_dimension (GtkWidget        *widget,
       if (aux_info && aux_info->width > 0)
        return aux_info->width;
       else
-       return widget->requisition.width;
+       {
+         /* XXX Possibly we should be using natural values and not minimums here. */
+         gint width;
+
+         gtk_extended_layout_get_desired_width (GTK_EXTENDED_LAYOUT (widget), &width, NULL);
+
+         return width;
+       }
     }
   else
     {
       if (aux_info && aux_info->height > 0)
        return aux_info->height;
       else
-       return widget->requisition.height;
-    }
-}
+       {
+         /* XXX Possibly we should be using natural values and not minimums here. */
+         gint height;
 
-static void
-do_size_request (GtkWidget *widget, gint width, gint height)
-{
-  if (GTK_WIDGET_REQUEST_NEEDED (widget))
-    {
-      gtk_widget_ensure_style (widget);      
-      GTK_PRIVATE_UNSET_FLAG (widget, GTK_REQUEST_NEEDED);
-      g_signal_emit_by_name (widget,
-                            "size-request",
-                            &widget->requisition);
-    }
-  
-  /* Also update size groups from _gtk_size_group_bump_requisition() */
-  widget->requisition.width  = MAX (widget->requisition.width, width);
-  widget->requisition.height = MAX (widget->requisition.height, height);
-}
+         gtk_extended_layout_get_desired_height (GTK_EXTENDED_LAYOUT (widget), &height, NULL);
 
-/* NOTE: This is only ever called for either mode horizontal or mode vertical
- * but never as both.
- */
-static gint
-compute_base_dimension (GtkWidget        *widget,
-                       GtkSizeGroupMode  mode,
-                       gint              minimum)
-{
-  if (mode == GTK_SIZE_GROUP_HORIZONTAL)
-    do_size_request (widget, minimum, -1);
-  else /*  (mode == GTK_SIZE_GROUP_VERTICAL) */
-    do_size_request (widget, -1, minimum);
-
-  return get_base_dimension (widget, mode);
+         return height;
+       }
+    }
 }
 
-/* NOTE: This is only ever called for either mode horizontal or mode vertical
- * but never as both.
- */
 static gint
 compute_dimension (GtkWidget        *widget,
                   GtkSizeGroupMode  mode,
-                  gint              minimum)
+                  gint              widget_requisition)
 {
   GSList *widgets = NULL;
   GSList *groups = NULL;
@@ -675,7 +670,7 @@ compute_dimension (GtkWidget        *widget,
   
   if (!groups)
     {
-      result = compute_base_dimension (widget, mode, minimum);
+      result = widget_requisition;
     }
   else
     {
@@ -691,8 +686,12 @@ compute_dimension (GtkWidget        *widget,
          while (tmp_list)
            {
              GtkWidget *tmp_widget = tmp_list->data;
+             gint dimension;
 
-             gint dimension = compute_base_dimension (tmp_widget, mode, minimum);
+             if (tmp_widget == widget)
+               dimension = widget_requisition;
+             else
+               dimension = get_base_dimension (tmp_widget, mode);
 
              if (gtk_widget_get_mapped (tmp_widget) || !group->ignore_hidden)
                {
@@ -711,12 +710,12 @@ compute_dimension (GtkWidget        *widget,
              if (mode == GTK_SIZE_GROUP_HORIZONTAL)
                {
                  tmp_group->have_width = TRUE;
-                 tmp_group->requisition.width = MAX (result, minimum);
+                 tmp_group->requisition.width = result;
                }
              else
                {
                  tmp_group->have_height = TRUE;
-                 tmp_group->requisition.height = MAX (result, minimum);
+                 tmp_group->requisition.height = result;
                }
              
              tmp_list = tmp_list->next;
@@ -732,162 +731,39 @@ compute_dimension (GtkWidget        *widget,
   return result;
 }
 
-static gint
-get_dimension (GtkWidget        *widget,
-              GtkSizeGroupMode  mode)
-{
-  GSList *widgets = NULL;
-  GSList *groups = NULL;
-  gint result = 0;
-
-  add_widget_to_closure (widget, mode, &groups, &widgets);
-
-  g_slist_foreach (widgets, (GFunc)mark_unvisited, NULL);
-  g_slist_foreach (groups, (GFunc)mark_unvisited, NULL);  
-
-  if (!groups)
-    {
-      result = get_base_dimension (widget, mode);
-    }
-  else
-    {
-      GtkSizeGroup *group = groups->data;
-
-      if (mode == GTK_SIZE_GROUP_HORIZONTAL && group->have_width)
-       result = group->requisition.width;
-      else if (mode == GTK_SIZE_GROUP_VERTICAL && group->have_height)
-       result = group->requisition.height;
-    }
-
-  g_slist_free (widgets);
-  g_slist_free (groups);
-
-  return result;
-}
-
-static void
-get_fast_child_requisition (GtkWidget      *widget,
-                           GtkRequisition *requisition)
-{
-  GtkWidgetAuxInfo *aux_info = _gtk_widget_get_aux_info (widget, FALSE);
-  
-  *requisition = widget->requisition;
-  
-  if (aux_info)
-    {
-      if (aux_info->width > 0)
-       requisition->width = aux_info->width;
-      if (aux_info && aux_info->height > 0)
-       requisition->height = aux_info->height;
-    }
-}
-
-/**
- * _gtk_size_group_get_child_requisition:
- * @widget: a #GtkWidget
- * @requisition: location to store computed requisition.
- * 
- * Retrieve the "child requisition" of the widget, taking account grouping
- * of the widget's requisition with other widgets.
- **/
-void
-_gtk_size_group_get_child_requisition (GtkWidget      *widget,
-                                      GtkRequisition *requisition)
-{
-  initialize_size_group_quarks ();
-
-  if (requisition)
-    {
-      if (get_size_groups (widget))
-       {
-         requisition->width = get_dimension (widget, GTK_SIZE_GROUP_HORIZONTAL);
-         requisition->height = get_dimension (widget, GTK_SIZE_GROUP_VERTICAL);
-
-         /* Only do the full computation if we actually have size groups */
-       }
-      else
-       get_fast_child_requisition (widget, requisition);
-    }
-}
-
-/**
- * _gtk_size_group_compute_requisition:
- * @widget: a #GtkWidget
- * @requisition: location to store computed requisition.
- * 
- * Compute the requisition of a widget taking into account grouping of
- * the widget's requisition with other widgets.
- *
- * This is used by #GtkExtendedLayout to obtain minimum value
- * caps for all values cached and returned to parent containers,
- * then the extended layout while making its own sizes in multiple
- * passes updates sizegroups with _gtk_size_group_bump_requisition().
- */
-void
-_gtk_size_group_compute_requisition (GtkWidget      *widget,
-                                    GtkRequisition *requisition)
-{
-  gint width;
-  gint height;
-
-  initialize_size_group_quarks ();
-
-  if (get_size_groups (widget))
-    {
-      /* Only do the full computation if we actually have size groups */
-      width = compute_dimension (widget, GTK_SIZE_GROUP_HORIZONTAL, -1);
-      height = compute_dimension (widget, GTK_SIZE_GROUP_VERTICAL, -1);
-
-      if (requisition)
-       {
-         requisition->width = width;
-         requisition->height = height;
-       }
-    }
-  else
-    {
-      do_size_request (widget, -1, -1);
-      
-      if (requisition)
-       get_fast_child_requisition (widget, requisition);
-    }
-}
-
-
 /**
  * _gtk_size_group_bump_requisition:
  * @widget: a #GtkWidget
  * @mode: either %GTK_SIZE_GROUP_HORIZONTAL or %GTK_SIZE_GROUP_VERTICAL, depending
  *        on the dimension in which to bump the size.
- * @size: The new base size in @mode's dimension for the group.
+ *
+ * Refreshes the sizegroup while returning the groups requested
+ * value in the dimension @mode.
  *
  * This function is used to update sizegroup minimum size information
  * in multiple passes from the new #GtkExtendedLayout manager.
  */
-void
+gint
 _gtk_size_group_bump_requisition (GtkWidget        *widget,
                                  GtkSizeGroupMode  mode,
-                                 gint              size)
+                                 gint              widget_requisition)
 {
-  initialize_size_group_quarks ();
+  gint result = widget_requisition;
 
-  if (get_size_groups (widget))
+  if (!is_bumping (widget) && get_size_groups (widget))
     {
-      if (mode == GTK_SIZE_GROUP_HORIZONTAL)
-       compute_dimension (widget, GTK_SIZE_GROUP_HORIZONTAL, size);
-      else
-       compute_dimension (widget, GTK_SIZE_GROUP_VERTICAL, size);
-    }
-  else
-    {
-      if (mode == GTK_SIZE_GROUP_HORIZONTAL)
-       do_size_request (widget, size, -1);
-      else
-       do_size_request (widget, -1, size);
+      /* Avoid recursion here */
+      mark_bumping (widget, TRUE);
+
+      result = compute_dimension (widget, mode, widget_requisition);
+
+      mark_bumping (widget, FALSE);
     }
+  return result;
 }
 
 
+
 /**
  * _gtk_size_group_queue_resize:
  * @widget: a #GtkWidget
index 8addb5cd7a1d55736296a42497e9601b6a86527d..28a06e956754c54ce513f9ebb9bbc4977c9a680d 100644 (file)
@@ -100,13 +100,10 @@ void             gtk_size_group_remove_widget (GtkSizeGroup     *size_group,
 GSList *         gtk_size_group_get_widgets   (GtkSizeGroup     *size_group);
 
 
-void _gtk_size_group_get_child_requisition (GtkWidget        *widget,
-                                           GtkRequisition   *requisition);
-void _gtk_size_group_compute_requisition   (GtkWidget        *widget,
-                                           GtkRequisition   *requisition);
-void _gtk_size_group_bump_requisition      (GtkWidget        *widget,
+
+gint _gtk_size_group_bump_requisition      (GtkWidget        *widget,
                                            GtkSizeGroupMode  mode,
-                                           gint              size);
+                                           gint              widget_requisition);
 void _gtk_size_group_queue_resize          (GtkWidget        *widget);
 
 
index a72ad6a566c7342e9a2efca92ea6137e7d08354b..2407c779b1fe7647e8ec0af469e7ad40ec63d770 100644 (file)
@@ -3928,7 +3928,7 @@ void
 gtk_widget_get_child_requisition (GtkWidget     *widget,
                                  GtkRequisition *requisition)
 {
-  _gtk_size_group_get_child_requisition (widget, requisition);
+  gtk_extended_layout_get_desired_size (GTK_EXTENDED_LAYOUT (widget), requisition, NULL);
 }
 
 static gboolean
@@ -9282,9 +9282,6 @@ _gtk_widget_get_aux_info (GtkWidget *widget,
       aux_info->width = -1;
       aux_info->height = -1;
 
-      aux_info->cached_width_age  = 1;
-      aux_info->cached_height_age = 1;
-
       g_object_set_qdata (G_OBJECT (widget), quark_aux_info, aux_info);
     }